#include "TsPacket.h"

/*demux Transport stream based on the synch byte*/
int TsPacket::demuxTS(char * stream, int length, TsPacket ** ts_packet_array,
		int & ts_nbr) {
	int j = 0;
	const unsigned int synch = 0x47;
	int i = 0;

	while (i < length) {
		if ((memcmp(&(stream[i]), &synch, 1) == 0) && ((i + 188 >= length)
				|| (memcmp(&(stream[i + 188]), &synch, 1) == 0))

		) {

			ts_packet_array[j] = new TsPacket(&(stream[i]), TS_PACKET_LENGTH);
			j++;
			i += 188; //should be 188 but unalignament is around the corner;

		} else {
			i++;
		}

	}
	ts_nbr = j;

	return 0;
}

TsPacket::TsPacket(char * buffer, int length) {
	this->buffer = buffer;
	this->length = length;

}

bool TsPacket::isTsPacket() {
	return 0;
}

bool TsPacket::getPayload(char * &payload, int & length) {
	switch (this->getAdaptationFieldControl()) {
	case 0x00:
		return false;
		break;
	case 0x01:
		payload = &(this->buffer[4]);
		length = this->length - 5;
		return true;
		break;
	case 0x02:
		return false;
		break;
	case 0x03:

		payload = &(this->buffer[4+this->getAdaptationFieldLength()]);
		length = this->length - (5+this->getAdaptationFieldLength());
		return true;
		break;

	default:
		return false;
		break;
	}
}

unsigned int TsPacket::getPID() {
	return (((this->buffer[1] & 0x1f) << 8) | this->buffer[2]);
}

char TsPacket::getContinuityCounter() {
	return (this->buffer[3] & 0x0f);
}

int TsPacket::getAdaptationFieldControl() {
	return (this->buffer[3] >> 4) & 0x03;
}

bool TsPacket::isAdaptationPresent() {
	return (this->getAdaptationFieldControl() > 0x01);
}

long long int TsPacket::getPCR() {
	if (getPCRFlag())
	{
		return  ((this->buffer[6] & 0xff) << 25) |
				((this->buffer[7] & 0xff) << 17) |
				((this->buffer[8] & 0xff) << 9 ) |
				((this->buffer[9] & 0xff) << 1 ) |
                ((this->buffer[10] & 0x80)>>7);
	}else{
		return -1;
	}
}

char TsPacket::getAdaptationFieldLength(){
	return this->buffer[4];
}

bool TsPacket::getPCRFlag() {
	return (this->isAdaptationPresent() && (this->getAdaptationFieldLength() >= 0)
			&& (this->buffer[5] & 0x10) == 0x10);

}

